//
//  ZMRefactorAndDestructExtension.swift
//  collectionview的使用
//
//  Created by pg on 2017/7/20.
//  Copyright © 2017年 pg. All rights reserved.
//

import Foundation
import UIKit

enum ZMRefactorDirection{
    case Horizontal
    case Vertical
    case Diagonal
    case Custom
}


extension CGRect{
    var centerPoint: CGPoint{
        return CGPoint(x: origin.x + size.width / 2, y: origin.y + size.height / 2)
    }
}

extension UIView{
    
       
  
    
    func moveToframe(finallyFrame:CGRect,animationTime: TimeInterval,animationComplation:@escaping(()->())){
        
        guard let _ = self.superview else{
            return
        }
        
        let fromViewSnapshot = self.snapshotView(afterScreenUpdates: true)
        
        self.alpha = 0.0
        
        let ratio: CGFloat = 0.1
      let size =  finallyFrame.size
        let pieceWidth: CGFloat = size.width * ratio
        let pieceHeight: CGFloat = size.height * ratio
        
        let (column, row) = columnAndRow(size: size, ratio: ratio)
        let delayDelta: Double = animationTime / Double(column * row)
        let piecesRect = filterRect(jumpRect: self.frame)
        
        var snapshots: [UIView] = []
        
        var ignoreIndexSet:Set<Int> = []
        var index = 0
        var delay: TimeInterval = 0
        var cleanTime: TimeInterval = 0
        
        for y in stride(from: CGFloat(0), to: size.height, by: pieceHeight) {
            
            for x in stride(from: CGFloat(0),to: size.width, by: pieceWidth) {
                
                index += 1
                if ignoreIndexSet.contains(index){
                    continue
                }
                
                let indexOffset = ignoreIndexSet.reduce(0, {
                    delta, element in
                    let gap = element < index ? delta + 1 : delta
                    return gap
                })
                let (snapshotRegion, addedSet) = snapshotInfo(enableBigRegion: false, index: index, xy: (x, y), widthXheight: (pieceWidth, pieceHeight), columnXrow: (column, row))
                
                let initialFrame = randomRectFrom(sourceRect: piecesRect, regionSize: snapshotRegion.size)
                let finalFrame = finallyFrame
                
                if addedSet.count > 0{
                    ignoreIndexSet.formUnion(addedSet)
                }
                
                let snapshot = fromViewSnapshot?.resizableSnapshotView(from: snapshotRegion, afterScreenUpdates: false, withCapInsets: UIEdgeInsets.zero)
                self.superview!.addSubview(snapshot!)
                snapshots.append(snapshot!)
                snapshot?.frame = initialFrame
                snapshot?.alpha = 0
                
               
                
                delay = delayDelta * Double(index - indexOffset)
                
                let duration: TimeInterval = animationTime + 0.1 * Double(UInt32(arc4random()) % UInt32(3))
                cleanTime = (delay + duration + 0.5 > cleanTime) ? delay + duration + 0.5 : cleanTime
                
                
                UIView.animate(withDuration: 0.1, delay: delay, options: UIViewAnimationOptions.beginFromCurrentState, animations: {
                    snapshot?.alpha = 1
                }, completion: { _ in
                    
                    UIView.animate(withDuration: duration, delay: 0, options: UIViewAnimationOptions.beginFromCurrentState, animations: {
                        
                        snapshot?.frame = finalFrame
                        
                        self.frame = finalFrame
                    }, completion: { (isfinished) in
                        
                        animationComplation()
                        self.alpha = 1
                        snapshot?.alpha = 0
                    })
                })
                
                
            }
        }
        //can't rely on dispatch_after, which can't guarantee the exact execution time
        self.perform(#selector(cleanUp(snapshots:)), with: snapshots, afterDelay: cleanTime)
        
        
    }
    private func randomRectFrom(sourceRect: CGRect, regionSize: CGSize) -> CGRect {
        
        //let deltaBase = UInt32(min(min(sourceRect.width, sourceRect.height), 300.0))
        //let delta = CGFloat(arc4random() % deltaBase)
        //let factor: CGFloat = Int(UInt32(arc4random()) % UInt32(2)) == 1 ? -1.0 : 1.0
        
        let randomX: CGFloat = sourceRect.origin.x - sourceRect.size.width / 2 + CGFloat(UInt32(arc4random()) % UInt32( 2.0 * sourceRect.size.width )) //+ factor * delta
        let randomY: CGFloat = sourceRect.origin.y - sourceRect.size.height / 2 + CGFloat(UInt32(arc4random()) % UInt32( 2.0 * sourceRect.size.height )) //- factor * delta
        
        let initialFrame = CGRect(x: randomX, y: randomY, width: regionSize.width, height: regionSize.height)
        
        return initialFrame
    }

    
    private func snapshotInfo(enableBigRegion: Bool, index: Int, xy: (CGFloat, CGFloat), widthXheight: (CGFloat, CGFloat), columnXrow: (Int, Int)) -> (CGRect, Set<Int>){
        
        let (pieceWidth, pieceHeight) = widthXheight
        
        let isBigRegion = enableBigRegion ? Int(UInt32(arc4random()) % UInt32(2)) == 1 : false
        var regionWidth = isBigRegion ? 2.0 * pieceWidth : pieceWidth
        var regionHeith = isBigRegion ? 2.0 * pieceHeight : pieceHeight
        
        let (regionX, regionY) = xy
        
        let size = self.frame.size
        if regionX + regionWidth >= size.width{
            regionWidth = size.width - regionX
        }
        if regionY + regionHeith >= size.height{
            regionHeith = size.height - regionY
        }
        
        let (column, _) = columnXrow
        var ignoreIndexSet: Set<Int> = []
        
        if isBigRegion {
            if regionX + pieceWidth < size.width{
                ignoreIndexSet.insert(index + 1)
            }
            
            if regionY + pieceHeight < size.height{
                ignoreIndexSet.insert(index + column)
                
                if regionX + pieceWidth < size.width{
                    ignoreIndexSet.insert(index + column + 1)
                }
            }
        }
        
        let regionOrigin: CGPoint = CGPoint(x: regionX, y: regionY)
        let regionSize: CGSize = CGSize(width: regionWidth, height: regionHeith)
        let snapshotRegion = CGRect(origin: regionOrigin, size: regionSize)
        
        return (snapshotRegion, ignoreIndexSet)
    }
//MARK:-返回每行有多少块,每列有多少块
   private func columnAndRow(size:CGSize,ratio:CGFloat)->(Int,Int){
    
    var rowCount = 0
    for _ in stride(from: CGFloat(0), to: size.height, by: size.height*ratio) {
        rowCount += 1
    }
    
    var columnCount = 0
    for _ in stride(from: CGFloat(0), to: size.width, by: size.width*ratio) {
        columnCount += 1
        
    }
    
    return (columnCount,rowCount)
}

 private func filterRect(jumpRect : CGRect?) -> CGRect {
    
    var piecesRect = self.frame
    
    let screenRect = UIScreen.main.bounds
    
    if jumpRect != nil {
        
        if screenRect.contains(jumpRect!) {
            piecesRect = jumpRect!
        }else{
            
            if !screenRect.intersection(jumpRect!).isNull{
                
                piecesRect = screenRect.intersection(jumpRect!)
                
            }else{
                let bigRect = self.frame.insetBy(dx: -self.frame.size.width/2, dy: -self.frame.size.height/2)
                
                piecesRect = screenRect.intersection(bigRect)
           }
            
            
        }
    }else{
        let bigrect =  self.frame.insetBy(dx: -self.frame.size.width/2, dy: -self.frame.size.height/2)
        
        piecesRect = screenRect.intersection(bigrect)
    }
    
    
    return piecesRect
}

    
    private func diagonalIndexFor(index: Int, columnXrow:(Int, Int)) -> Int{
        
        let (column, _) = columnXrow
        let x = index % column == 0 ? column : index % column
        let y = (index - x + column) / column
        let DiagonalIndex = x + y - 1
        return DiagonalIndex
    }


    
     @objc private func cleanUp(snapshots: [UIView]){
        self.alpha = 1
        for snapshot in snapshots{
            snapshot.removeFromSuperview()
        }
        
    }
    
    @objc private func windUp(snapshots: [UIView]){
        for snapshot in snapshots{
            snapshot.removeFromSuperview()
        }
    }


}









